#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <asm/ioctl.h>
#include "hi_type.h"
#include "hi_comm_aio.h"
#include "acodec.h"
#include "app_common.h"
#include "ProductManager.h"

#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* __cplusplus */

#define ACODEC_FILE     "/dev/acodec"

HI_S32 ADPT_ACODEC_Init(AUDIO_SAMPLE_RATE_E enSampleRate)
{
    static char bInit = 0;

    if (bInit == 1) {
        return HI_SUCCESS;
    }
    
    HI_S32 fdAcodec = -1;
    HI_S32 ret = HI_SUCCESS;
    ACODEC_FS_E i2s_fs_sel = 0;
    int iAcodecInputVol = 0;
    int iAcodecOutputVol = 0;
    ACODEC_MIXER_E input_mode = 0;
    unsigned int mute_ctrl= 0x0;

    fdAcodec = open(ACODEC_FILE, O_RDWR);
    if (fdAcodec < 0)
    {
        LOGE("%s: can't open Acodec,%s\n", __FUNCTION__, ACODEC_FILE);
        return HI_FAILURE;
    }

    switch (enSampleRate)
    {
        case AUDIO_SAMPLE_RATE_8000:
            i2s_fs_sel = ACODEC_FS_8000;
            break;

        case AUDIO_SAMPLE_RATE_16000:
            i2s_fs_sel = ACODEC_FS_16000;
            break;

                case AUDIO_SAMPLE_RATE_32000:
                    i2s_fs_sel = ACODEC_FS_32000;
                    break;

                case AUDIO_SAMPLE_RATE_11025:
                    i2s_fs_sel = ACODEC_FS_11025;
                    break;

                case AUDIO_SAMPLE_RATE_22050:
                    i2s_fs_sel = ACODEC_FS_22050;
                    break;

                case AUDIO_SAMPLE_RATE_44100:
                    i2s_fs_sel = ACODEC_FS_44100;
                    break;

                case AUDIO_SAMPLE_RATE_24000:
                    i2s_fs_sel = ACODEC_FS_24000;
                    break;

        case AUDIO_SAMPLE_RATE_48000:
            i2s_fs_sel = ACODEC_FS_48000;
            break;

        case AUDIO_SAMPLE_RATE_96000:
            i2s_fs_sel = ACODEC_FS_96000;
            break;
        default:
            LOGW("%s: not support enSample:%d\n", __FUNCTION__, enSampleRate);
        close(fdAcodec);
            return HI_FAILURE;
    }

    if (ioctl(fdAcodec, ACODEC_SET_I2S1_FS, &i2s_fs_sel))
    {
        LOGE("%s: set acodec sample rate failed\n", __FUNCTION__);
        close(fdAcodec);
        return HI_FAILURE;
    }

    if (PRODUCT_MODEL_B1 == ProductGetHandle()->ProductModel) {
        input_mode = ACODEC_MIXER_IN_D;
    } else if (PRODUCT_MODEL_B5 == ProductGetHandle()->ProductModel) {
        input_mode = ACODEC_MIXER_IN1;
    } else {
        input_mode = ACODEC_MIXER_IN_D;
    }
    if (ioctl(fdAcodec, ACODEC_SET_MIXER_MIC, &input_mode))
    {
        LOGE("%s: select acodec input_mode failed\n", __FUNCTION__);
        close(fdAcodec);
        return HI_FAILURE;
    }

    if (1) /* should be 1 when micin */
    {
        /******************************************************************************************
        The input volume range is [-87, +86]. Both the analog gain and digital gain are adjusted.
        A larger value indicates higher volume.
        For example, the value 86 indicates the maximum volume of 86 dB,
        and the value -87 indicates the minimum volume (muted status).
        The volume adjustment takes effect simultaneously in the audio-left and audio-right channels.
        The recommended volume range is [+10, +56].
        Within this range, the noises are lowest because only the analog gain is adjusted,
        and the voice quality can be guaranteed.
        *******************************************************************************************/ 
        iAcodecInputVol = 50; //mic gain
        if (ioctl(fdAcodec, ACODEC_SET_INPUT_VOL, &iAcodecInputVol))
        {
            LOGE("ACODEC_SET_INPUT_VOL failed\n");
            return HI_FAILURE;
        }

        /******************************************************************************************
        The output volume range is [-121, +6]. The volume 6 is the max volume, 6dB.
        The volume -121 is the min volume, is mute.
        *******************************************************************************************/   
        iAcodecOutputVol = 5; //speak gain
        if (ioctl(fdAcodec, ACODEC_SET_OUTPUT_VOL, &iAcodecOutputVol))
        {
            LOGE("ACODEC_SET_OUTPUT_VOL failed\n");
            return HI_FAILURE;
        }        
    }
    
/*
    if (ioctl(fdAcodec, ACODEC_SET_MICL_MUTE, &mute_ctrl))
    {
        printf("%s: ACODEC_SET_MICL_MUTE failed\n", __FUNCTION__);
        close(fdAcodec);
        return HI_FAILURE;
    }
    if (ioctl(fdAcodec, ACODEC_SET_MICR_MUTE, &mute_ctrl))
    {
        printf("%s: ACODEC_SET_MICR_MUTE failed\n", __FUNCTION__);
        close(fdAcodec);
        return HI_FAILURE;
    }
    */
    close(fdAcodec);

    bInit = 1;
    
    return HI_SUCCESS;
}

HI_S32 ADPT_ACODEC_DeInit()
{
    return HI_SUCCESS;
}

HI_S32 ADPT_ACODEC_SetAIVol(HI_S32 s32Vol)
{
    HI_S32 fdAcodec = -1;
    ACODEC_VOL_CTRL stVolCtrl;
    
    fdAcodec = open(ACODEC_FILE, O_RDWR);
    if (fdAcodec < 0) {
        LOGE("%s: can't open Acodec,%s\n", __FUNCTION__, ACODEC_FILE);
        return HI_FAILURE;
    }
    
    stVolCtrl.vol_ctrl_mute = 0;
    stVolCtrl.vol_ctrl = 100 - s32Vol;
    if (ioctl(fdAcodec, ACODEC_SET_ADCL_VOL, &stVolCtrl)) {
        LOGE("ACODEC_SET_ADCL_VOL volume failed\n");
        close(fdAcodec);
        return HI_FAILURE;
    }
    
    close(fdAcodec);
    return HI_SUCCESS;
}

HI_S32 ADPT_ACODEC_GetAIVol(HI_S32* s32Vol)
{
    HI_S32 fdAcodec = -1;
    ACODEC_VOL_CTRL stVolCtrl;
    
    fdAcodec = open(ACODEC_FILE, O_RDWR);
    if (fdAcodec < 0) {
        LOGE("%s: can't open Acodec,%s\n", __FUNCTION__, ACODEC_FILE);
        return HI_FAILURE;
    }
    
    memset(&stVolCtrl, 0, sizeof(stVolCtrl));
    if (ioctl(fdAcodec, ACODEC_GET_ADCL_VOL, &stVolCtrl)) {
        LOGE("ACODEC_GET_ADCL_VOL volume failed\n");
        close(fdAcodec);
        return HI_FAILURE;
    }

    *s32Vol = stVolCtrl.vol_ctrl;
    
    close(fdAcodec);
    return HI_SUCCESS;
}

HI_S32 ADPT_ACODEC_MuteAI()
{
    HI_S32 fdAcodec = -1;
    HI_S32 s32InputVol = 0;
    HI_S32 ret = HI_SUCCESS;
    fdAcodec = open(ACODEC_FILE, O_RDWR);
    if (fdAcodec < 0)
    {
        LOGE("%s: can't open Acodec,%s\n", __FUNCTION__, ACODEC_FILE);
        return HI_FAILURE;
    }
    unsigned int mute_ctrl;
    mute_ctrl = 0x1;
    if (ioctl(fdAcodec, ACODEC_SET_MICL_MUTE, &mute_ctrl))
    {
        LOGE("%s: ACODEC_SET_MICL_MUTE failed\n", __FUNCTION__);
        close(fdAcodec);
        return HI_FAILURE;
    }
    if (ioctl(fdAcodec, ACODEC_SET_DACL_MUTE, &mute_ctrl))
    {
        LOGE("%s: ACODEC_SET_MICL_MUTE failed\n", __FUNCTION__);
        close(fdAcodec);
        return HI_FAILURE;
    }
    if (ioctl(fdAcodec, ACODEC_SET_MICR_MUTE, &mute_ctrl))
    {
        LOGE("%s: ACODEC_SET_MICR_MUTE failed\n", __FUNCTION__);
        close(fdAcodec);
        return HI_FAILURE;
    }
    if (ioctl(fdAcodec, ACODEC_SET_DACR_MUTE, &mute_ctrl))
    {
        LOGE("%s: ACODEC_SET_DACR_MUTE failed\n", __FUNCTION__);
        close(fdAcodec);
        return HI_FAILURE;
    }
    close(fdAcodec);
    return HI_SUCCESS;
}

HI_S32 ADPT_ACODEC_UnMuteAI()
{
    HI_S32 fdAcodec = -1;
    HI_S32 s32InputVol = 0;
    HI_S32 ret = HI_SUCCESS;
    fdAcodec = open(ACODEC_FILE, O_RDWR);
    if (fdAcodec < 0)
    {
        LOGE("%s: can't open Acodec,%s\n", __FUNCTION__, ACODEC_FILE);
        return HI_FAILURE;
    }
    unsigned int mute_ctrl;
    mute_ctrl = 0x0;
    if (ioctl(fdAcodec, ACODEC_SET_MICL_MUTE, &mute_ctrl))
    {
        LOGE("%s: ACODEC_SET_MICL_MUTE failed\n", __FUNCTION__);
        close(fdAcodec);
        return HI_FAILURE;
    }
    if (ioctl(fdAcodec, ACODEC_SET_DACL_MUTE, &mute_ctrl))
    {
        LOGE("%s: ACODEC_SET_MICL_MUTE failed\n", __FUNCTION__);
        close(fdAcodec);
        return HI_FAILURE;
    }
    if (ioctl(fdAcodec, ACODEC_SET_MICR_MUTE, &mute_ctrl))
    {
        LOGE("%s: ACODEC_SET_MICR_MUTE failed\n", __FUNCTION__);
        close(fdAcodec);
        return HI_FAILURE;
    }
    if (ioctl(fdAcodec, ACODEC_SET_DACR_MUTE, &mute_ctrl))
    {
        LOGE("%s: ACODEC_SET_DACR_MUTE failed\n", __FUNCTION__);
        close(fdAcodec);
        return HI_FAILURE;
    }
    close(fdAcodec);
    return HI_SUCCESS;
}


HI_S32 ADPT_ACODEC_SetAOVol(HI_S32 s32Vol)
{
    HI_S32 fdAcodec = -1;
    ACODEC_VOL_CTRL stVolCtrl;
    
    fdAcodec = open(ACODEC_FILE, O_RDWR);
    if (fdAcodec < 0) {
        LOGE("%s: can't open Acodec,%s\n", __FUNCTION__, ACODEC_FILE);
        return HI_FAILURE;
    }
    
    stVolCtrl.vol_ctrl_mute = 0;
    stVolCtrl.vol_ctrl = 100 - s32Vol;
    if (ioctl(fdAcodec, ACODEC_SET_DACL_VOL, &stVolCtrl)) {
        LOGE("ACODEC_SET_DACL_VOL volume failed\n");
        close(fdAcodec);
        return HI_FAILURE;
    }
    
    close(fdAcodec);
    return HI_SUCCESS;
}

HI_S32 ADPT_ACODEC_GetAOVol(HI_S32* s32Vol)
{
    HI_S32 fdAcodec = -1;
    ACODEC_VOL_CTRL stVolCtrl;
    
    fdAcodec = open(ACODEC_FILE, O_RDWR);
    if (fdAcodec < 0) {
        LOGE("%s: can't open Acodec,%s\n", __FUNCTION__, ACODEC_FILE);
        return HI_FAILURE;
    }
    
    memset(&stVolCtrl, 0, sizeof(stVolCtrl));
    if (ioctl(fdAcodec, ACODEC_GET_DACL_VOL, &stVolCtrl)) {
        LOGE("ACODEC_SET_DACL_VOL volume failed\n");
        close(fdAcodec);
        return HI_FAILURE;
    }

    *s32Vol = stVolCtrl.vol_ctrl;
    
    close(fdAcodec);
    return HI_SUCCESS;
}

#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */
